package ae.pcfc.cldos.online.common.facade.provider;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.transaction.annotation.Transactional;

import ae.pcfc.cldos.online.common.ConstantsCommon;
import ae.pcfc.cldos.online.common.ConstantsCommon.Steps;
import ae.pcfc.cldos.online.common.UltimusConstants;
import ae.pcfc.cldos.online.common.UltimusConstants.ApplicationResubmitDecision;
import ae.pcfc.cldos.online.common.UltimusConstants.EmployeeType;
import ae.pcfc.cldos.online.common.clddb.domain.AppMetaData;
import ae.pcfc.cldos.online.common.clddb.domain.ApplicationStatus;
import ae.pcfc.cldos.online.common.clddb.domain.EmploymentVisaRenew;
import ae.pcfc.cldos.online.common.clddb.domain.Process;
import ae.pcfc.cldos.online.common.clddb.domain.ReviewComments;
import ae.pcfc.cldos.online.common.clddb.domain.ServiceMaster;
import ae.pcfc.cldos.online.common.clddb.domain.TaskMaster;
import ae.pcfc.cldos.online.common.clddb.domain.TempFileStorage;
import ae.pcfc.cldos.online.common.clddb.domain.manager.EmploymentVisaRenewDOM;
import ae.pcfc.cldos.online.common.etksdb.domain.User;
import ae.pcfc.cldos.online.common.exception.BadAppException;
import ae.pcfc.cldos.online.common.exception.InvalidEmpIdException;
import ae.pcfc.cldos.online.common.exception.UltimusAppException;
import ae.pcfc.cldos.online.common.facade.BaseProcesesFacade;
import ae.pcfc.cldos.online.common.facade.EmploymentVisaRenewalFacade;
import ae.pcfc.cldos.online.common.factories.AppMetaDataFactory;
import ae.pcfc.cldos.online.common.vo.AppSaveResponseVO;
import ae.pcfc.cldos.online.common.vo.FileVO;
import ae.pcfc.cldos.online.common.vo.UserVO;
import ae.pcfc.cldos.online.common.vo.ev.ren.can.EmploymentVisaRenewalDetailsVO;
import ae.pcfc.cldos.online.common.vo.ev.ren.can.EmploymentVisaRenewalVO;
import ae.pcfc.cldos.online.common.vo.fnp.FNPPaymentAdviceVO;
import ae.pcfc.cldos.online.gs.ConstantsGS;
import ae.pcfc.cldos.online.gs.service.client.vo.NotificationVO;
import ae.pcfc.cldos.online.wf.ConstantsWF;
import ae.pcfc.cldos.online.wf.service.client.vo.appdata.EmploymentVisaRenewAppInfo;
import ae.pcfc.cldos.online.wf.service.client.vo.base.CompleteStepVO;
import ae.pcfc.cldos.online.wf.service.client.vo.base.LaunchIncedentVO;
import ae.pcfc.cldos.online.wf.service.client.vo.gvar.EVRenewalReSubmGVarVO;
import ae.pcfc.cldos.online.wf.service.client.vo.gvar.EVRenewalSubmGVarVO;

/**
 * 
 * @author arosa
 *
 */
public class EmploymentVisaRenewalFacadeImpl extends BaseProcesesFacade implements EmploymentVisaRenewalFacade {

	private EmploymentVisaRenewDOM employmentVisaRenewDOM;
	
	public void setEmploymentVisaRenewDOM(
			EmploymentVisaRenewDOM employmentVisaRenewDOM) {
		this.employmentVisaRenewDOM = employmentVisaRenewDOM;
	}
	
	@Transactional
	public EmploymentVisaRenewalVO getEmploymentVisaRenewalAppInfo(String appId, UserVO userVO, Steps step) throws BadAppException{
		
		EmploymentVisaRenewalVO employmentVisaRenewalVO = new EmploymentVisaRenewalVO();
		AppMetaData appMetaData = null;
		
		if(userVO.isGeneralAdmin()){
			appMetaData = appMetaDataDOM
				.getAppMetaDataByIdForGeneralAdmin(appId, Process.PROCESS_EMPLOYMENT_VISA_RENEWAL, step);
		} else {
			User user = userDomainObjectManager.findUserByUserName(userVO.getUsername());
			appMetaData = appMetaDataDOM
					.getAppMetaDataById(appId, Process.PROCESS_EMPLOYMENT_VISA_RENEWAL, step, user.getClientId());
		}
		EmploymentVisaRenewalDetailsVO employmentVisaRenewalDetailsVO = 
				new EmploymentVisaRenewalDetailsVO();
		getMapper().map(appMetaData.getEmploymentVisaRenew(), employmentVisaRenewalDetailsVO);
		employmentVisaRenewalVO.setEmploymentVisaRenewalDetailsVO(employmentVisaRenewalDetailsVO);
		
		employmentVisaRenewalVO.setClientReferenceNo(appMetaData.getClientRefNo());
		employmentVisaRenewalVO.setInitiatedBy(appMetaData.getWfInitiatedBy());
		
		List<TempFileStorage> tempFileStoragesList = appMetaData.getTempFileStorages();
		List<FileVO> fileVOList = new ArrayList<FileVO>(tempFileStoragesList.size());
		for(TempFileStorage tempFileStorage : tempFileStoragesList){
			FileVO fileVO = new FileVO();
			getMapper().map(tempFileStorage, fileVO);
			fileVOList.add(fileVO);
		}
		employmentVisaRenewalVO.setFileVOList(fileVOList);
		employmentVisaRenewalVO.setApplicationCommentVOs(getCommentsVOList(appMetaData.getReviewComments()));
		try{
			employmentVisaRenewalVO.setWfStatus(gsInfoManager.getWfStatus(employmentVisaRenewalVO.getClientReferenceNo()));
		}catch(Exception e){
			employmentVisaRenewalVO.setWfStatus(ConstantsGS.EMP_STATUS_NA);
		}
		return employmentVisaRenewalVO;
	}
	
	@Transactional(rollbackFor=Exception.class)
	public AppSaveResponseVO submit(EmploymentVisaRenewalVO employmentVisaRenewalVO) throws Exception{
		return storeToDb(employmentVisaRenewalVO, null, false);
	}
	
	@Transactional(rollbackFor=Exception.class)
	public AppSaveResponseVO reSubmit(EmploymentVisaRenewalVO employmentVisaRenewalVO, String appId) throws Exception{
		return storeToDb(employmentVisaRenewalVO, appId, true);
	}
	
	private AppSaveResponseVO storeToDb(EmploymentVisaRenewalVO employmentVisaRenewalVO, String appId, boolean isResubmit) throws Exception{
		AppSaveResponseVO appSaveResponseVO = new AppSaveResponseVO();
		Integer incident = null; 
		
		UserVO userVO =  employmentVisaRenewalVO.getUserVO();
		User user = userDomainObjectManager.findUserAndClientByUserName(userVO.getUsername());
				
		String compLicNo = tTscClientCompanyDOM.getLicenseNumberNyTrakheesId(user.getClient().getCTrakheesId());
		/*if(!gsEmployeeDetailsManager.validateEmployee(employmentVisaRenewalVO.getEmploymentVisaRenewalDetailsVO().getEvrEmployeeId(), 
				compLicNo)){
			throw new InvalidEmpIdException();
		}
		if(userVO.isAdmin()){
			buisnessValidationManager.validateCompany(compLicNo);
		}*/
		
		if(userVO.isAdmin()){
			buisnessValidationManager.validateOnlineEmpVisaRenewalData(compLicNo,employmentVisaRenewalVO.getEmploymentVisaRenewalDetailsVO().getEvrEmployeeId());
			gsInfoManager.isRequestExist(Process.PROCESS_EMPLOYMENT_VISA_RENEWAL,employmentVisaRenewalVO.getEmploymentVisaRenewalDetailsVO().getEvrEmployeeId(), null);
			if(!gsEmployeeDetailsManager.validateEmployee(employmentVisaRenewalVO.getEmploymentVisaRenewalDetailsVO().getEvrEmployeeId(), 
					compLicNo)){
				throw new InvalidEmpIdException();
			}
		}
		
		AppMetaDataFactory appMetaDataFactory = null;
		String clientRefNo = null;
		boolean backOfficeRejectflag=false;
		if(isResubmit){
			AppMetaData appMetaData = appMetaDataDOM.getAppMetaDataById(appId, 
					Process.PROCESS_EMPLOYMENT_VISA_RENEWAL, Steps.RESUBMIT, user.getClientId());
			appMetaDataFactory = AppMetaDataFactory.createReSubmitFactory(appMetaData);
			if(appMetaData.getStatusCode()==5){
				backOfficeRejectflag=true;
			}
			if(userVO.isAdmin() && !backOfficeRejectflag){
				clientRefNo = gsInfoManager.getNextOfflineAppId(Process.PROCESS_EMPLOYMENT_VISA_RENEWAL);
				appMetaData.setClientRefNo(clientRefNo);
			}
		} else {
				if(userVO.isAdmin()){
					clientRefNo = gsInfoManager.getNextOfflineAppId(Process.PROCESS_EMPLOYMENT_VISA_RENEWAL);
				}
				appMetaDataFactory = AppMetaDataFactory.createSubmitFactory(clientRefNo);
		}
		
		AppMetaData appMetaData = appMetaDataFactory.getAppMetaData();
		
		Long serviceCode =  ServiceMaster.EV_RENEVAL;
		appMetaData.setServiceCode(serviceCode);
		
		if(userVO.isAdmin()){
			appMetaData.setStatusCode(ApplicationStatus.STATUS_APPROVED_BY_ONLINE_ADMIN);
		}else if (!isResubmit) {
			appMetaData.setStatusCode(ApplicationStatus.STATUS_INITIATED);
		} else {
			appMetaData.setStatusCode(ApplicationStatus.STATUS_RESUBMITED);
		}
		
		appMetaData.setProcessCode(Process.PROCESS_EMPLOYMENT_VISA_RENEWAL);
		appMetaData.setUserId(user.getUId());
		appMetaData.setClientId(user.getClientId());
		appMetaData.setApplicationDate(new Date());
		if(!isResubmit || appMetaData.getApplicationId()==null){
			appMetaDataDOM.add(appMetaData);
		}
		
		
		if(isResubmit){
			taskAndNotificationsManager.completeAllByAppId(appMetaData.getApplicationId());
		}
		
		if(!userVO.isAdmin()){	
			taskAndNotificationsManager.sendTask(appMetaData, TaskMaster.__ADMIN_APPROVE_TASK_CODE);
		}
		
		EmploymentVisaRenew employmentVisaRenew = appMetaDataFactory.getEmploymentVisaRenew();
		getMapper().map(employmentVisaRenewalVO.getEmploymentVisaRenewalDetailsVO(), employmentVisaRenew);
		employmentVisaRenew.setAppMetaData(appMetaData);
		employmentVisaRenewDOM.add(employmentVisaRenew);
		appMetaData.setEmploymentVisaRenew(employmentVisaRenew);
		
		String referenceNumber = appMetaData.getApplicationId().toString();
		if(!userVO.isAdmin() && !backOfficeRejectflag){
			appMetaData.setClientRefNo(referenceNumber);
		}
		
		appMetaData.setTempFileStorages(fileStorageManager.storeFiles(appMetaData, employmentVisaRenewalVO.getFileVOList(), 
				appMetaDataFactory.getTempFileStoragesMap()));
		
		//add list of param here
		if(userVO.isAdmin()){
			 String fnpServiceCode = employmentVisaRenewalVO.getFnpServiceCode();
			 FNPPaymentAdviceVO fnpPaymentAdviceVO = 
					 fnpManager.generatePayment(appMetaData.getApplicationId(), userVO.getUsername(), fnpServiceCode, 
							 employmentVisaRenewalVO.getFnpParams(),null,appMetaData.getClientRefNo());
			 appMetaData.setPaymentAdviceNo(fnpPaymentAdviceVO.getPaymentAdviceNumber());
			 appMetaData.getTempFileStorages().add(fnpPaymentAdviceVO.getStoredPaymentAdvice());
		}
		EmploymentVisaRenewAppInfo employmentVisaRenewAppInfo = new EmploymentVisaRenewAppInfo();
		getMapper().map(employmentVisaRenewalVO.getEmploymentVisaRenewalDetailsVO(), employmentVisaRenewAppInfo);
		employmentVisaRenewAppInfo.setG_Post_No(appMetaData.getClientRefNo());
		
		/*add action comment*/
		ReviewComments reviewComments = new ReviewComments();
		reviewComments.setApplicationId(appMetaData.getApplicationId());
		reviewComments.setStatusCode(appMetaData.getStatusCode());
		reviewComments.setRcUserName(user.getUUsername());
		reviewComments.setRcComments(employmentVisaRenewalVO.getComment());
		reviewCommentsDOM.add(reviewComments);
		
		/*Send notification*/
		//if(!userVO.isAdmin()){
			NotificationVO notificationVO = new NotificationVO();
			notificationVO.setOnlineAppId(appMetaData.getApplicationId().toString());
			Map<Object, Object> parameters = new HashMap<Object, Object>();
			parameters.put("comments", employmentVisaRenewalVO.getComment());
			notificationVO.setParameters(parameters);
			taskAndNotificationsManager.sendNotification(appMetaData, notificationVO);
		//}
		
		//launch workflow
		if(appMetaData.getWfIncidentId() == null){
			if(userVO.isAdmin()){
				LaunchIncedentVO launchIncedentVO = new LaunchIncedentVO();
				
				EVRenewalSubmGVarVO evRenewalSubmGVarVO = new EVRenewalSubmGVarVO();
				evRenewalSubmGVarVO.setG_ApplicationID(referenceNumber);
				evRenewalSubmGVarVO.setG_ApplicationSubmissionMedium(ConstantsCommon.APPLICATION_SUBMISSION_MEDIUM_ONLINE);
				evRenewalSubmGVarVO.setG_ApplicationLaunchedBy(EmployeeType.COMPANY_ADMIN.getEmployeeType());
				evRenewalSubmGVarVO.setG_MedAppLetterSubMethod(employmentVisaRenewalVO.getEmploymentVisaRenewalDetailsVO().getEvrMedLetterSubmission());
				try{		
					incident = genericVisaWF.launchIncident(appMetaData.getProcessCode(), launchIncedentVO, evRenewalSubmGVarVO, employmentVisaRenewAppInfo);
				}catch (Exception e) {
					e.printStackTrace();
					fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), userVO.getUsername(), appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
					throw new UltimusAppException(e);
				}
				appMetaData.setWfIncidentId(incident.toString());
				appMetaData.setWfInitiatedBy(user.getUUsername());
			}
		} else{
			 incident = Integer.parseInt(appMetaData.getWfIncidentId());
			
			//:TODO put code for WF inwocation for resubmit
			EVRenewalReSubmGVarVO evRenewalReSubmGVarVO = new EVRenewalReSubmGVarVO();
			evRenewalReSubmGVarVO.setG_ApplicationID(referenceNumber);
			if(!userVO.isAdmin()){
				evRenewalReSubmGVarVO.setG_ApplicationResubmittedBy(EmployeeType.EMPLOYEE.getEmployeeType());
			}else{
				evRenewalReSubmGVarVO.setG_ApplicationResubmittedBy(EmployeeType.COMPANY_ADMIN.getEmployeeType());
			}
			evRenewalReSubmGVarVO.setG_ApplicationResubmitDecision(ApplicationResubmitDecision.RESUBMITTED.getResubmitDecision());
			evRenewalReSubmGVarVO.setG_MedAppLetterSubMethod(
					employmentVisaRenewalVO.getEmploymentVisaRenewalDetailsVO().getEvrMedLetterSubmission());
			
			CompleteStepVO completeStepVO = new CompleteStepVO();
			completeStepVO.setStrStepName(UltimusConstants.RESUBMIT_ONLINE_APPLICATION_STEP);
			completeStepVO.setStrUserName(ConstantsWF.ULTIMUS_ANONYMOUS_USER);
			completeStepVO.setnIncidentNumber(incident);
			
			try{		
				genericVisaWF.completeStep(appMetaData.getProcessCode(), completeStepVO, evRenewalReSubmGVarVO, 
						employmentVisaRenewAppInfo);
			}catch (Exception e) {
				e.printStackTrace();
				if(userVO.isAdmin()){
					fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), userVO.getUsername(), appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
				}
				throw new UltimusAppException(e);
			}
		}
		
		/*
		 * transfer request to GS
		 */
			transferDataToGS(appMetaData, userVO, compLicNo);
		/*
		 * end of transfer
		 */
		
		if(isResubmit){
			appMetaDataDOM.update(appMetaData);
		} else {
			appMetaDataDOM.updateAndAddEtks(appMetaData);
		}
		
		appSaveResponseVO.setReferenceNo(appMetaData.getClientRefNo());
		appSaveResponseVO.setIncidentNo(appMetaData.getWfIncidentId());
		return appSaveResponseVO;
	}
}
